//
//  MKCollectionModel.m
//  MKUI
//
//  Created by sushangjin on 14/11/19.
//  Copyright © 2020 sushangjin. All rights reserved.
//

#import "MKCollectionModel.h"
#import "MKCollectionSectionModel.h"
#import "MKCollectionCellModel.h"

@interface MKCollectionModel(){
	NSMutableArray<MKCollectionSectionModel *> *_sectionModels;
}
@end

@implementation MKCollectionModel
- (id)init{
	if (self=[super init]) {
		_sectionModels = [[NSMutableArray alloc] init];
		self.allowsSelection = YES;
	}
	return self;
}
- (id)copyWithZone:(NSZone *)zone{
    MKCollectionModel *obj = [super copyWithZone:zone];
    obj->_sectionModels = [_sectionModels mutableCopy];
    for(MKCollectionSectionModel *sm in self.sectionModels){
        sm.collectionModel = self;
    }
    obj.userInfo = self.userInfo;
    obj.allowsSelection = self.allowsSelection;
    obj.allowsMultipleSelection = self.allowsMultipleSelection;
    obj.allowsFocus = self.allowsFocus;
    return obj;
}
- (NSMutableArray<__kindof MKCollectionSectionModel *> *)mutableSectionModels{
	return _sectionModels;
}
- (NSIndexPath *)indexPathOfLastCellModel{
	NSIndexPath *indexpath;
	NSInteger sections = self.numberOfSections;
	for (NSInteger i=sections-1;i>=0;i--) {
		MKCollectionSectionModel *sm = [self sectionModelAtIndex:i];
		NSInteger cells = sm.numberOfCells;
		if(cells>0){
			indexpath = [NSIndexPath indexPathForItem:cells-1 inSection:i];
			break;
		}
	}
	return indexpath;
}
- (NSArray<__kindof MKCollectionSectionModel *> *)sectionModels{
	return [self mutableSectionModels];
}
- (void)setSectionModels:(NSArray<MKCollectionSectionModel *> *)sectionModels{
	[[self mutableSectionModels] removeAllObjects];
	[[self mutableSectionModels] addObjectsFromArray:sectionModels];
    for(MKCollectionSectionModel *sm in sectionModels){
        sm.collectionModel = self;
    }
}
- (NSInteger)numberOfSections{
	NSInteger number = [self sectionModels].count;
	return number;
}
- (NSInteger)numberOfCells{
	NSInteger numberOfCells = 0;
	for (MKCollectionSectionModel *section in [self sectionModels]) {
		numberOfCells += [section numberOfCells];
	}
	return numberOfCells;
}
- (NSArray<__kindof MKCollectionCellModel *> *)allCellModels{
	NSMutableArray<MKCollectionCellModel *> *cells = [[NSMutableArray alloc] init];
	for (MKCollectionSectionModel *section in [self sectionModels]) {
		[cells addObjectsFromArray:[section cellModels]];
	}
	return cells;
}
- (__kindof MKCollectionSectionModel *)createEmptySectionModel{
	MKCollectionSectionModel *section = [[MKCollectionSectionModel alloc] init];
	return section;
}
- (void)addCellModel:(MKCollectionCellModel *)cellModel{
	if(!cellModel)return;
	MKCollectionSectionModel *section = [[self sectionModels] lastObject];
	if(!section){
		section = [self createEmptySectionModel];
		[self addSectionModel:section];
	}
	[section addCellModel:cellModel];
}
- (void)addCellModelToFirst:(MKCollectionCellModel *)cellModel{
	if(!cellModel)return;
	MKCollectionSectionModel *section = [[self sectionModels] firstObject];
	if(!section){
		section = [self createEmptySectionModel];
		[self addSectionModel:section];
	}
	[section insertCellModel:cellModel atIndex:0];
}
- (void)addCellModels:(NSArray<MKCollectionCellModel *> *)cellModels{
	for (MKCollectionCellModel *cellModel in cellModels) {
		[self addCellModel:cellModel];
	}
}
- (void)insertCellModel:(MKCollectionCellModel *)cellModel atIndexPath:(NSIndexPath *)indexPath{
	if(!cellModel)return;
	MKCollectionSectionModel *sectionModel = [self sectionModelAtIndex:indexPath.section];
	if(sectionModel){
		[sectionModel insertCellModel:cellModel atIndex:indexPath.row];
	}
}
- (void)insertCellModels:(NSArray<MKCollectionCellModel *> *)cellModels afterIndexPath:(NSIndexPath *)indexPath{
	if(cellModels.count==0||!indexPath)return;
	MKCollectionSectionModel *sectionModel = [self sectionModelAtIndex:indexPath.section];
	if(sectionModel){
		[sectionModel insertCellModels:cellModels afterIndex:indexPath.row];
	}
}
- (void)insertCellModels:(NSArray<MKCollectionCellModel *> *)cellModels beforeIndexPath:(NSIndexPath *)indexPath{
	if(cellModels.count==0||!indexPath)return;
	MKCollectionSectionModel *sectionModel = [self sectionModelAtIndex:indexPath.section];
	if(sectionModel){
		[sectionModel insertCellModels:cellModels beforeIndex:indexPath.row];
	}
}
- (void)insertCellModelsToBottom:(NSArray<MKCollectionCellModel *> *)cellModels{
	if(cellModels.count==0)return;
	MKCollectionSectionModel *sectionModel = [[self sectionModels] lastObject];
	if(sectionModel){
		[sectionModel insertCellModelsToBottom:cellModels];
	}
}
- (void)insertCellModelsToTop:(NSArray<MKCollectionCellModel *> *)cellModels{
	if(cellModels.count==0)return;
	MKCollectionSectionModel *sectionModel = [[self sectionModels] firstObject];
	if(sectionModel){
		[sectionModel insertCellModelsToTop:cellModels];
	}
}
- (void)removeCellModel:(MKCollectionCellModel *)cellModel{
	for (MKCollectionSectionModel *section in [self sectionModels]) {
		[section removeCellModel:cellModel];
	}
}
- (void)removeCellModels:(NSArray<MKCollectionCellModel *> *)cellModels{
	for (MKCollectionCellModel *cellModel in cellModels) {
		[self removeCellModel:cellModel];
	}
}
- (void)removeCellModelAtIndexPath:(NSIndexPath *)indexPath{
	MKCollectionSectionModel *sectionModel = [self sectionModelAtIndex:indexPath.section];
	[sectionModel removeCellModelAtIndex:indexPath.row];
}
- (void)removeCellModelsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths{
	if(indexPaths.count==0)return;
    NSMutableDictionary *sectionMap = [[NSMutableDictionary alloc] init];
    for (NSIndexPath *p in indexPaths) {
        NSInteger section = p.section;
        NSMutableArray<NSIndexPath *> *paths = sectionMap[@(section)];
        if(!paths){
            paths = [[NSMutableArray alloc] initWithObjects:p, nil];
            sectionMap[@(section)] = paths;
        }
        [paths addObject:p];
    }
	for (NSNumber *sectionNum in sectionMap) {
		NSArray<NSIndexPath *> *subIndexPaths = sectionMap[sectionNum];
		NSMutableIndexSet *indexset = [[NSMutableIndexSet alloc] init];
		for (NSIndexPath *indexpath in subIndexPaths) {
			[indexset addIndex:indexpath.row];
		}
		MKCollectionSectionModel *sectionModel = [self sectionModelAtIndex:[sectionNum integerValue]];
		[sectionModel removeCellModelsAtIndexes:indexset];
	}
}
- (void)addSectionModel:(MKCollectionSectionModel *)sectionModel{
	if(!sectionModel)return;
	sectionModel.collectionModel = self;
	[[self mutableSectionModels] addObject:sectionModel];
}
- (void)insertSectionModel:(MKCollectionSectionModel *)sectionModel atIndex:(NSInteger)index{
	if(!sectionModel)return;
	sectionModel.collectionModel = self;
	[[self mutableSectionModels] insertObject:sectionModel atIndex:index];
}
- (void)addSectionModels:(NSArray<MKCollectionSectionModel *> *)sectionModels{
	for (MKCollectionSectionModel *sectionModel in sectionModels) {
		[self addSectionModel:sectionModel];
	}
}
- (void)removeSectionModel:(MKCollectionSectionModel *)sectionModel{
	sectionModel.collectionModel = nil;
	[[self mutableSectionModels] removeObject:sectionModel];
}
- (void)removeSectionModelAtIndex:(NSInteger)index{
	if(index>=0&&index<[self mutableSectionModels].count){
		[[self mutableSectionModels] removeObjectAtIndex:index];
	}
}
- (void)removeSectionModelsInRange:(NSRange)range{
	[[self mutableSectionModels] removeObjectsInRange:range];
}
- (void)removeAllSectionModels{
	[[self mutableSectionModels] removeAllObjects];
}
- (NSIndexPath *)indexPathOfCellModel:(MKCollectionCellModel *)cellModel{
	__block NSIndexPath *indexpath = nil;
	[[self sectionModels] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
		MKCollectionSectionModel *section = obj;
		NSInteger row = [section indexOfCellModel:cellModel];
		if(row!=NSNotFound){
			indexpath = [NSIndexPath indexPathForRow:row inSection:idx];
			*stop = YES;
		}
	}];
	return indexpath;
}
- (void)enumerateCellModelsUsingBlock:(void(^)(id cellModel,NSIndexPath *indexpath,BOOL *stop))block{
	if(!block)return;
	NSInteger sectionIndex = 0;
	BOOL stop = NO;
	for (MKCollectionSectionModel *sm in self.sectionModels) {
		NSInteger itemIndex = 0;
		for (MKCollectionCellModel *cellModel in sm.cellModels) {
			NSIndexPath *indexpath = [NSIndexPath indexPathForItem:itemIndex inSection:sectionIndex];
			block(cellModel,indexpath,&stop);
			if(stop){
				return;
			}
			itemIndex++;
		}
		sectionIndex++;
	}
}
- (NSIndexPath *)indexPathOfCellModelPassingTest:(BOOL(^)(id cellModel,NSIndexPath *indexpath,BOOL *stop))block{
	if(!block)return nil;
	__block NSIndexPath *result;
	[self enumerateCellModelsUsingBlock:^(id cellModel, NSIndexPath *indexpath, BOOL *stop) {
		BOOL s = block(cellModel,indexpath,stop);
		if(s){
			result = indexpath;
			*stop = YES;
		}
	}];
	return result;
}
- (NSArray<NSIndexPath *> *)indexPathsOfCellModelPassingTest:(BOOL(^)(id cellModel,NSIndexPath *indexpath,BOOL *stop))block{
	NSMutableArray<NSIndexPath *> *indexpaths = [[NSMutableArray alloc] init];
	[self enumerateCellModelsUsingBlock:^(id cellModel, NSIndexPath *indexpath, BOOL *stop) {
		BOOL s = block(cellModel,indexpath,stop);
		if(s){
			[indexpaths addObject:indexpath];
		}
	}];
	return indexpaths;
}
- (NSArray<NSIndexPath *> *)indexPathsOfCellModels:(NSArray<MKCollectionCellModel *> *)cellModels{
	NSMutableArray<NSIndexPath *> *indexPaths = [[NSMutableArray alloc] initWithCapacity:cellModels.count];
	for (MKCollectionCellModel *cellModel in cellModels) {
		NSIndexPath *indexPath = [self indexPathOfCellModel:cellModel];
		if(indexPath){
			[indexPaths addObject:indexPath];
		}
	}
	return indexPaths;
}
- (NSInteger)indexOfSectionModel:(MKCollectionSectionModel *)sectionModel{
	NSInteger index = [[self sectionModels] indexOfObject:sectionModel];
	return index;
}
- (NSIndexSet *)indexSetOfSectionModel:(MKCollectionSectionModel *)sectionModel{
	NSInteger index = [[self sectionModels] indexOfObject:sectionModel];
	NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
	return indexSet;
}
- (MKCollectionCellModel *)cellModelAtIndexPath:(NSIndexPath *)indexpath{
	if(!indexpath)return nil;
	MKCollectionSectionModel *section = [self sectionModelAtIndex:indexpath.section];
	MKCollectionCellModel *cell = [section cellModelAtIndex:indexpath.row];
	return cell;
}
- (NSArray<__kindof MKCollectionCellModel *> *)cellModelsAtIndexPaths:(NSArray<NSIndexPath *> *)indexpaths{
	NSMutableArray<MKCollectionCellModel *> *cellModels = [[NSMutableArray alloc] init];
	for (NSIndexPath *indexpath in indexpaths) {
		id cm = [self cellModelAtIndexPath:indexpath];
		if(cm){
			[cellModels addObject:cm];
		}
	}
	return cellModels;
}
- (MKCollectionSectionModel *)sectionModelAtIndex:(NSInteger)index{
	MKCollectionSectionModel *sectionModel;
	if(index>=0&&index<[self sectionModels].count){
		sectionModel = [[self sectionModels] objectAtIndex:index];
	}
	return sectionModel;
}
- (void)removeEmptySectionModels{
	NSArray<MKCollectionSectionModel *> *sectionModels = [self emptySectionModels];
	[[self mutableSectionModels] removeObjectsInArray:sectionModels];
}
- (NSArray<__kindof MKCollectionSectionModel *> *)emptySectionModels{
	NSMutableArray<MKCollectionSectionModel *> *sectionModels = [[NSMutableArray alloc] init];
	for (MKCollectionSectionModel *sm in [self sectionModels]) {
		if(sm.numberOfCells==0){
			[sectionModels addObject:sm];
		}
	}
	return sectionModels;
}
- (void)moveCellModelAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
	if(sourceIndexPath==nil||destinationIndexPath==nil)return;
	MKCollectionCellModel *sourceCellModel = [self cellModelAtIndexPath:sourceIndexPath];
	[self removeCellModelAtIndexPath:sourceIndexPath];
	[self insertCellModel:sourceCellModel atIndexPath:destinationIndexPath];
}

- (void)selectCellModelAtIndexPath:(NSIndexPath *)indexPath{
	MKCollectionCellModel *cellModel = [self cellModelAtIndexPath:indexPath];
	[self selectCellModel:cellModel];
}
- (void)selectCellModelsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths{
	NSArray<MKCollectionCellModel *> *cellModels = [self cellModelsAtIndexPaths:indexPaths];
	[self selectCellModels:cellModels];
}
- (void)selectCellModel:(MKCollectionCellModel *)cellModel{
	if(self.allowsSelection){
		if(!self.allowsMultipleSelection){
			NSArray<MKCollectionCellModel *> *allCells = [self allCellModels];
			for (MKCollectionCellModel *cm in allCells) {
				if(![cm isEqual:cellModel]){
					cm.selected = NO;
				}
			}
		}
		cellModel.selected = YES;
	}
}
- (void)selectCellModels:(NSArray<MKCollectionCellModel *> *)cellModels{
	if(self.allowsSelection){
		if(self.allowsMultipleSelection){
			for (MKCollectionCellModel *cellModel in cellModels) {
				cellModel.selected = YES;
			}
		}
	}
}
- (void)selectAllCellModels{
	[self selectCellModels:[self allCellModels]];
}
- (void)deselectCellModelAtIndexPath:(NSIndexPath *)indexPath{
	MKCollectionCellModel *cellModel = [self cellModelAtIndexPath:indexPath];
	[self deselectCellModel:cellModel];
}
- (void)deselectCellModel:(MKCollectionCellModel *)cellModel{
	cellModel.selected = NO;
}
- (void)deselectCellModels:(NSArray<MKCollectionCellModel *> *)cellModels{
	for (MKCollectionCellModel *cellModel in cellModels) {
		[self deselectCellModel:cellModel];
	}
}
- (void)deselectAllCellModels{
	[self deselectCellModels:[self allCellModels]];
}
- (NSIndexPath *)indexPathForSelectedCellModel{
	for (int i=0;i<[self sectionModels].count;i++) {
		MKCollectionSectionModel *sm = [self sectionModels][i];
		NSArray<MKCollectionCellModel *> *cellModels = sm.cellModels;
		for (int j=0; j<cellModels.count; j++) {
			MKCollectionCellModel *cm = cellModels[j];
			if(cm.selected){
				NSIndexPath *indexpath = [NSIndexPath indexPathForItem:j inSection:i];
				return indexpath;
			}
		}
	}
	return nil;
}
- (__kindof MKCollectionCellModel *)cellModelForSelectedCellModel{
	for (MKCollectionSectionModel *sm in [self sectionModels]) {
		NSArray<MKCollectionCellModel *> *cellModels = sm.cellModels;
		for (MKCollectionCellModel *cm in cellModels) {
			if(cm.selected){
				return cm;
			}
		}
	}
	return nil;
}
- (NSArray<NSIndexPath *> *)indexPathsForSelectedCellModels{
	NSMutableArray<NSIndexPath *> *indexpaths = [[NSMutableArray alloc] init];
	for (int i=0;i<[self sectionModels].count;i++) {
		MKCollectionSectionModel *sm = [self sectionModels][i];
		NSArray<MKCollectionCellModel *> *cellModels = sm.cellModels;
		for (int j=0; j<cellModels.count; j++) {
			MKCollectionCellModel *cm = cellModels[j];
			if(cm.selected){
				NSIndexPath *indexpath = [NSIndexPath indexPathForItem:j inSection:i];
				[indexpaths addObject:indexpath];
			}
		}
	}
	return indexpaths;
}
- (NSArray<__kindof MKCollectionCellModel *> *)cellModelsForSelectedCellModels{
	NSMutableArray<MKCollectionCellModel *> *cellModels = [[NSMutableArray alloc] init];
	for (MKCollectionSectionModel *sm in [self sectionModels]) {
		NSArray<MKCollectionCellModel *> *cms = sm.cellModels;
		for (MKCollectionCellModel *cm in cms) {
			if(cm.selected){
				[cellModels addObject:cm];
			}
		}
	}
	return cellModels;
}
@end
@implementation MKCollectionModel(Focused)
- (NSIndexPath *)indexPathForFocusedCellModel{
	for (int i=0;i<[self sectionModels].count;i++) {
		MKCollectionSectionModel *sm = [self sectionModels][i];
		NSArray<MKCollectionCellModel *> *cellModels = sm.cellModels;
		for (int j=0; j<cellModels.count; j++) {
			MKCollectionCellModel *cm = cellModels[j];
			if(cm.focused){
				NSIndexPath *indexpath = [NSIndexPath indexPathForItem:j inSection:i];
				return indexpath;
			}
		}
	}
	return nil;
}
- (__kindof MKCollectionCellModel *)cellModelForFocusedCellModel{
	for (MKCollectionSectionModel *sm in [self sectionModels]) {
		NSArray<MKCollectionCellModel *> *cellModels = sm.cellModels;
		for (MKCollectionCellModel *cm in cellModels) {
			if(cm.focused){
				return cm;
			}
		}
	}
	return nil;
}
- (void)focusCellModelAtIndexPath:(NSIndexPath *)indexpath focused:(BOOL)focused{
	if(!self.allowsFocus){
		return;
	}
	MKCollectionCellModel *cellModel = [self cellModelAtIndexPath:indexpath];
	[self focusCellModel:cellModel focused:focused];
}
- (void)focusCellModel:(MKCollectionCellModel *)cellModel focused:(BOOL)focused{
	if(!self.allowsFocus){
		return;
	}
	if(focused){
		MKCollectionCellModel *oldCellModel = self.cellModelForFocusedCellModel;
		oldCellModel.focused = NO;
	}
	cellModel.focused = focused;
}
- (void)focusNone{
	if(!self.allowsFocus){
		return;
	}
	MKCollectionCellModel *oldCellModel = self.cellModelForFocusedCellModel;
	oldCellModel.focused = NO;
}
@end
